package domain;

import dto.DayAcquisitionDTO;
import model.ReadExcelUtil;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

/**
 * @author 刀氏春秋
 * @date 2023/6/1
 */
public class TSNEDataDO {
    /**
     * 单相表数据，只要96个横轴点
     */
    Map<String, List<Double>> X = new HashMap<>();

    /**
     * 数据项序号同电表资产号的映射
     */
    Map<String, Integer> indexMap = new HashMap<>();

    public void initData(String filename) {
        // 读取数据，因为只考虑电压，所以只代入电压即可
        ReadExcelUtil<DayAcquisitionDTO> reader = new ReadExcelUtil<>();
        List<DayAcquisitionDTO> data = reader.readRawDataFromExcel(filename, DayAcquisitionDTO.class);

        // 通过反射获取到DTO类的方法名，用于后续取数据
        Class<DayAcquisitionDTO> dtoClass = DayAcquisitionDTO.class;

        try {
            for (DayAcquisitionDTO item : data) {
                List<Double> pointOfMeter = new LinkedList<>();
                // 通过反射式调用获取数据
                for (int i = 1; i <= 96; i++) {
                    String getMethod = "getI" + i;
                    // DTO item 逐个调用get方法
                    Double voltage = (Double) dtoClass.getDeclaredMethod(getMethod).invoke(item);
                    if (voltage != null) pointOfMeter.add(voltage);
                }
                System.out.printf("%s: %d points.%n", item.getAssetNo(), pointOfMeter.size());
                if (pointOfMeter.size() == 96) this.X.put(item.getAssetNo(), pointOfMeter);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 获取96点数据，不含其他任何信息
     * 对于没有采集到完整96点的数据，直接过滤掉
     *
     * @return 96维的电压数据
     */
    public double[][] get96PointData() {
        System.out.println(this.X.keySet());
        double[][] tsneData = new double[this.X.size()][96];

        // 逐个电表数据遍历
        int index = 0;
        for (String key : this.X.keySet()) {
            // 根据电表资产号取出电压召测数据，并将其赋值给目标数组
            for (int i = 0; i < 96; i++) {
                tsneData[index][i] = this.X.get(key).get(i);
            }

            // 由于代入的数据只有行序号，没有电表资产号，为了标记每个电表资产号对于哪一行数据，用map保存
            this.indexMap.put(key, index);
            index++;
        }
        return tsneData;
    }
}
